
package com.hlkj.pay.app.merchant.ext.impl.heepay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import com.hlkj.pay.app.merchant.ext.impl.hnapay.handler.HnapayMerchantCommonParamsHandle;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.heepay.HeePayScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayCommonRes;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayOrderQueryRes;
import com.hlkj.pay.app.merchant.ext.impl.heepay.handler.HeePayMerchantCommonParamsHandle;
import com.hlkj.pay.app.merchant.ext.impl.heepay.util.HynetUtil;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;

import cn.hutool.core.codec.Base64Encoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 条码支付，商户扫用户二维码收款
 * 
 * @author HlpayTeam
 * @date 2024/11/18 13:08
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = HeePayExtConstant.SCAN)
public class HeePayScanPayOrderExtPt extends HeePaySceneCommonPayOrder implements HeePayScenePayOrderExtPt {

    @Autowired
    private HeePayMerchantCommonParamsHandle heePayMerchantCommonParamsHandle;

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        HeePayConfig heePayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(merchantAppChannelDO,heePayConfig);
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        try {
            Map<String, String> params = new HashMap<>();
            params.put("version", "2");
            params.put("agent_id", heePayConfig.getAgentId());
            if(!MerchantEnum.APP_CHANNEL_TYPE.MERCHANT_COMMON.getCode().equals(merchantAppChannelDO.getType())){
                params.put("ref_agent_id", heliPayAppChannelParams.getHeePayId());
            }
            params.put("agent_bill_id", payOrderDO.getPayOrderNo());
            params.put("agent_bill_time", DateUtils.dateToString(System.currentTimeMillis(), "yyyyMMddHHmmss"));
            PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
            switch (payType) {
                case WECHAT:
                    params.put("provider_type", "1");
                    break;
                case ALIPAY:
                    params.put("provider_type", "2");
                    break;
            }
            PayOrderCommonParamReq.Extra extra = JsonUtils.parseObject(payOrderDO.getExtra(), PayOrderCommonParamReq.Extra.class);
            params.put("auth_code", extra.getAuthCode());
            // 调用 encrypt3DES 方法进行加密
            byte[] gbkBytes = extra.getAuthCode().getBytes(Charset.forName("GBK"));
            params.put("payment_info", HynetUtil.encrypt3DES(gbkBytes,heePayConfig.getDesKey()));
            params.put("pay_amt", MerchantUtils.bigDecimalToString2(payOrderDO.getAmount()));
            params.put("user_ip", payOrderDO.getClientIp());
            params.put("goods_name", heePayMerchantCommonParamsHandle.subject(payOrderDO.getSubject()));
            params.put("goods_num", "1");
            params.put("remark", "");

            boolean acct = false;
            if (!PayOrderEnums.FUND_PROCESS_TYPE.NO.getCode().equals(payOrderDO.getFundProcessType())) {
                acct = true;
            }
            if(acct){
                params.put("meta_option", Base64Encoder.encode("{\"is_guarantee\":\"1\"}"));
            }
            log.info("汇付宝 条码支付 请求参数:{}", JsonUtils.toJsonString(params));
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayOrderRequest(HeePayConstant.PAY_ORDER_SCAN_SUBMIT_URL,heePayConfig, params,
                    HeePayConstant.PAY_ORDER_SUBMIT_FIELD);
            log.info("汇付宝 条码支付 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelPayOrderContext.setRemark("汇付宝条码支付请求失败,失败信息" + resultResult.getMsg());
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            // String response = resultResult.getData();
            // HeePayOrderSubmitRes heePayOrderSubmitRes = JsonUtils.parseObject(response, HeePayOrderSubmitRes.class);
            // if (HeliPayConstant.REQUEST_SUCCESS.equals(heePayOrderSubmitRes.getCode())) {
            //     // channelPayOrderContext.setChannelOrderId(heePayOrderCommonRes.get());
            //     // channelPayOrderContext.setInsOrderNo(heePayOrderCommonRes.getRt16_outTransactionOrderId());
            //     channelPayOrderContext.setPayDataType("url");
            //     channelPayOrderContext.setPayInfo(heePayOrderSubmitRes.getQr_code_url());
            // }
            // else {
            //     channelPayOrderContext.setProcessStatus(Boolean.FALSE);
            //     if (StringUtils.hasText(heePayOrderSubmitRes.getMessage())) {
            //         channelPayOrderContext.setRemark(heePayOrderSubmitRes.getMessage());
            //     }
            //     else {
            //         channelPayOrderContext.setRemark("汇付宝提交条码支付返回错误信息为空,错误码为:" + heePayOrderSubmitRes.getCode());
            //     }
            // }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝提交条码支付请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("汇付宝提交条码支付请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelPayOrderQueryContext.getProviderChannelConfigDO(),
                channelPayOrderQueryContext.isTest());
        HeePayConfig heliPayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelPayOrderQueryContext.getPayOrderDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(channelPayOrderQueryContext.getMerchantAppChannelDO(),heliPayConfig);
        PayWayDO payWayDO = channelPayOrderQueryContext.getPayWayDO();
        try {
            Map<String, String> params = new HashMap<>();
            params.put("version", "1");
            params.put("agent_id", heliPayConfig.getAgentId());
            params.put("agent_bill_id", payOrderDO.getPayOrderNo());
            params.put("time_stamp", DateUtils.dateToString(System.currentTimeMillis(), "yyyyMMddHHmmss"));
            log.info("汇付宝 条码支付查询 请求参数:{}", JsonUtils.toJsonString(params));
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayOrderRequest(HeePayConstant.PAY_ORDER_SCAN_QUERY_URL, heliPayConfig, params,
                    HeePayConstant.PAY_ORDER_SCAN_QUERY_FIELD);
            log.info("汇付宝 条码支付查询 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelPayOrderQueryContext.setRemark("汇付宝条码支付查询请求失败,失败信息:" + resultResult.getMsg());
                channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            String response = resultResult.getData();
            HeePayCommonRes heliPayOrderQueryRes = JsonUtils.parseObject(response, HeePayCommonRes.class);
            PayOrderDO updartePayOrderDO = new PayOrderDO();
            channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
            if (HeePayConstant.ORDER_QUERY_SUCCESS.equals(heliPayOrderQueryRes.getCode())) {
                HeePayOrderQueryRes heePayOrderQueryRes = JsonUtils.parseObject(heliPayOrderQueryRes.getData(), HeePayOrderQueryRes.class);
                // 汇元单据状态，PROCESS=处理中 SUCCESS=成功 FAIL=失败
                switch (heePayOrderQueryRes.getTrade_status()) {
                    case "PROCESS":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
                        updartePayOrderDO.setBankMsg("");
                        break;
                    case "SUCCESS":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                        updartePayOrderDO.setBankMsg("");
                        break;
                    case "FAIL":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode());
                        break;

                }
                if (StringUtils.hasText(heePayOrderQueryRes.getPay_time())) {
                    try {
                        updartePayOrderDO.setSuccessTime(DateUtils.shanghaiDate(heePayOrderQueryRes.getPay_time(), "yyyy-MM-dd HH:mm:ss"));
                    }
                    catch (Exception e) {
                        log.error("汇付宝 条码支付查询 返回 时间格式化错误 dateTime:{},message:{}", heePayOrderQueryRes.getPay_time(), e.getMessage());
                    }
                }
                updartePayOrderDO.setInsOrderNo(heePayOrderQueryRes.getChannel_trade_no());
                updartePayOrderDO.setChannelOrderNo(heePayOrderQueryRes.getTrade_no());
                if (StringUtils.hasText(heePayOrderQueryRes.getPay_amt())) {
                    updartePayOrderDO.setPayAmount(MerchantUtils.stringToBigDecimal(heePayOrderQueryRes.getPay_amt()));
                }
                else {
                    updartePayOrderDO.setPayAmount(payOrderDO.getAmount());
                }
                if (StringUtils.hasText(heePayOrderQueryRes.getPay_user())) {
                    updartePayOrderDO.setUserId(heePayOrderQueryRes.getPay_user());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝 条码支付查询 请求失败 message:{}", e.getMessage(), e);
            channelPayOrderQueryContext.setRemark("汇付宝 条码支付查询 请求失败,失败信息" + e.getMessage());
            channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }
}
